/**
 * 变更标志
 * @type {{toBeDelete: 1, toBeAdd: 2, toBeModify: 3}}
 */

export const CHANGE_BIT_FLAG={
    //无变更,只做查看
    none: 0,
    //   &1:  新增 toBeAdd()    判断 true:需新增
    add: 1,
    //   &2:  修改 toBeModify() 判断 true:需更新
    modify: 2,
    //   &4:  修改 toBeDelete() 判断 true:需删除
    delete: 4,
}

/**
 * 显示字典标签cssClass
 * @type {{}}
 */
export const DICT_DATA_CSS_CLASS={
    /**
     * 默认(无class)
     */
    DEFAULT:"",
    /**
     * 字体红色
     */
    dictTextColorRed:"dict-text-color-red",
    /**
     * 字体绿色
     */
    dictTextColorGreen: "dict-text-color-green",
    /**
     * tag标签类型显示 primary  蓝色
     */
    dictTextTagPrimary:"dict-text-tag-primary",
    /**
     * tag标签类型显示 success  绿色
     */
    dictTextTagSuccess:"dict-text-tag-success",
    /**
     * tag标签类型显示 danger   红色
     */
    dictTextTagDanger:"dict-text-tag-danger",
    /**
     * tag标签类型显示 warning  黄色
     */
    dictTextTagWarning:"dict-text-tag-warning",
    /**
     * tag标签类型显示 info     灰色
     */
    dictTextTagInfo:"dict-text-tag-info",

}

//用于生成uuid
export function generateUUIDS4() {
    return (((1+Math.random())*0x10000)|0).toString(16).substring(1);
}

export function generateUUID() {
    return (generateUUIDS4()+generateUUIDS4()+""+generateUUIDS4()+""+generateUUIDS4()+""+generateUUIDS4()+""+generateUUIDS4()+generateUUIDS4()+generateUUIDS4());
}

/**
 * 为空或为 null 返回true
 * @param val
 * @return {boolean}
 */
export function isNullOrUndefined(val){
    return val === null||val === undefined
}

/**
 * 不为空且不为 null
 * @param val
 * @return {boolean}
 */
export function notNullAndNotUndefined(val){
    return !isNullOrUndefined(val)
}

//如果为空 则返回默认值
export function ifNull(val,defaultValue){
    return val === null||val === undefined?defaultValue:val
}

//判断对象是否相同,会转换为json之后再进行判断
export function equalsObj(a,b){
    if(a==b){
        return true
    }
    if(isNullOrUndefined(a)||isNullOrUndefined(b)){
        return false
    }
    return JSON.stringify(a) == JSON.stringify(b)
}

/**
 * @param num
 * @returns  true:num为空或为0,false:num不为空且不为0:
 */
export function numberIsZeroOrNull(num){
    if(num === undefined || num === null || num === 0 ||num === '0'){
        // console.log("numberIsZeroOrNull true",num)
        return true
    }
    if(num){
        // console.log("numberIsZeroOrNull false",num)
        return false;
    }
    return true;
    // return num?true:false;
}

/**
 *
 * @param num
 * @returns  true:num不为空且不为0,false:num为空或为0
 */
export function numberIsNotZeroOrNull(num){
    return !numberIsZeroOrNull(num);
}


/**
 * 关系解析,  比如 obj={a:{b:{c:'sks'}}}
 * 只需要 safeGet(obj,"a.b.c") 就可以获得字符串 sks
 * @param obj
 * @param propName
 */
export function safeGet(obj,relationshipName){
    if(obj===undefined||obj.constructor !== Object){
        return undefined;
    }
    let split = relationshipName.split(".")

    let item = obj
    for (let i in split) {
        const propName=split[i];
        if(item[propName]===undefined){
            return undefined;
        }
        item=item[propName];
        if(isNullOrUndefined(item)){
            return undefined;
        }
    }
    return item;
}


export function safeGetStr(obj,relationshipName){
    let str = safeGet(obj,relationshipName)
    return isNullOrUndefined(str)?'':str+''
}

export function safeGetNullEmpty(obj,relationshipName){
    return safeGet(obj,relationshipName)||''
}

/**
 * 深拷贝
 * @param obj
 * @return {string|undefined|null}
 */
export function deepCopy(obj){
    if(isNullOrUndefined(obj)){
        return obj==undefined?undefined:null;
    }
    // JSON.stringify(obj, null, 4)
    // return JSON.parse(JSON.stringify(obj, null),null)
    //如果存在 undefined 或被忽略,这里将 undefined 转换为 null
    return JSON.parse(objToJsonString(obj),null)
}

/**
 *
 * @param obj           要转为string的对象
 * @param space         json格式化缩进,为空则不缩进美化.
 *                      4: 美化,使用4个空格缩进
 * @return {string}
 */
export function objToJsonString(obj,space){
   return JSON.stringify(obj,(key,value)=>isNullOrUndefined(value)?null:value,space)
}

/**
 * 深拷贝
 * 合并对象,与extendObject相比,只要属性存在,未定义的也会覆盖掉最前面的值,是最基础的对象,返回target本身
 * @returns {{}}
 */
export function mergeFromObject() {
    const length = arguments.length
    if(length<1){
        return {}
    }
    const target = arguments[0]
    for (let i=0; i < length; i++) {
        let source = arguments[i]
        if(source===undefined||source===null||source.constructor !== Object){
            continue;
        }
        for (const key in source) {
            // 使用for in会遍历数组所有的可枚举属性，包括原型。
            if (Object.prototype.hasOwnProperty.call(source, key)) {
                // console.log("mergeFormObject,key",key,"value=",source[key])
                try{
                    //深拷贝
                    target[key] = cloneObject(source[key])
                }catch (e) {
                    console.log("key",key,"target",target,"cloneObject(source[key])",cloneObject(source[key]),"arguments",arguments)
                }
                // console.log("target[key]",target[key],"source[key]=",source[key])
            }
        }
    }
    return target
    // const length = arguments.length
    // for (const key in source) {
    //     // 使用for in会遍历数组所有的可枚举属性，包括原型。
    //     if (Object.prototype.hasOwnProperty.call(source, key)) {
    //         // console.log("key",key,"value=",source[key])
    //         target[key] = source[key]
    //         // console.log("target[key]",target[key],"source[key]=",source[key])
    //     }
    // }
    // return target
}

export function cloneObject(obj){
    let o
    // 如果  他是对象object的话  , 因为null,object,array  也是'object';
    if (typeof obj === 'object') {

        // 如果  他是空的话
        if (obj === null) {
            o = null;
        } else {

            // 如果  他是数组arr的话
            if (obj instanceof Array) {
                o = [];
                for (let i = 0, len = obj.length; i < len; i++) {
                    o.push(cloneObject(obj[ i ]));
                }
            }
            // 如果  他是对象object的话
            else {
                o = {};
                for (let j in obj) {
                    o[ j ] = cloneObject(obj[ j ]);
                }
            }

        }
    }else {
        o = obj;
    }
    return o;
}

//如果第一个参数中对象的属性值为 null 或者 undefined 才进行合并
//否则不变更源数据的值，适用于子对象，子数组
export function ifNullMergeFromObject(){
    const length = arguments.length
    if(length<1){
        return {}
    }
    const target = arguments[0]
    for (let i=0; i < length; i++) {
        const source = arguments[i]
        if(source===undefined||source===null||source.constructor !== Object){
            continue;
        }
        for (const key in source) {
            // 使用for in会遍历数组所有的可枚举属性，包括原型。
            if (Object.prototype.hasOwnProperty.call(source, key)) {
                if(isNullOrUndefined(target[key])){
                    //深拷贝
                    target[key] = cloneObject(source[key])
                }else{
                    //判断子级是否需要设置默认值
                    cloneObject(target[key],source[key])
                }
            }
        }
    }
    return target
}
/**
 * 查找list中对应字段相同的row
 * @param list
 * @param attrName      list中row的字段名
 * @param value         要查找的value值
 * @param typeEqual     类型是否一致,false:== , true:===
 * @returns {undefined|*}
 */
export function findRowInListFromAttrName(list,attrName,value,typeEqual=false){
    if (value == null) {
        return undefined;
    }
    if (isNullOrUndefined(list)||isNullOrUndefined(attrName)) {
        return undefined;
    }
    for (let i = 0; i < list.length; i++) {
        if(typeEqual){
            if (list[i][attrName] === value) {
                return list[i]
            }
        }else{
            if (list[i][attrName] == value) {
                return list[i]
            }
        }
    }
    return undefined;
}




/**
 * 第一个元素位置插入字典  全部
 * @param dictList
 * @returns {*}
 */
export function addShowAllToFirst(dictList){
    dictList.unshift({dictValue:"",dictLabel:"全部"})
    return dictList
}

/**
 * 字典的值类型变更为整数类型
 * @param dictList
 * @return {*}
 */
export function dictValueTypeToInteger(dictList){
    for (let row of dictList) {
        row.dictValue=Number(row.dictValue)
    }
    return dictList;
}

/**
 * 格式化文件大小为 nMB等格式
 * @param value
 * @param powerIn
 * @return {string}
 */
export function formatFileSize(value, powerIn) {
    const UNITS= ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']
    let power;
    if(powerIn===undefined){
        power=0;
        let i=value
        while ((i/1024) > 1){
            i=parseInt(i/1024)
            ++power;
        }
    }else{
        if(powerIn.constructor !== Number){
            power=UNITS.indexOf(powerIn.toUpperCase());
            if(power==-1){
                throw new Error("无效的第二参数,请使用以下数组任何一个",UNITS)
            }
        }else{
            power=powerIn
        }
    }
    return (value / Math.pow(1024, power)).toFixed(2) + UNITS[power];
}

/**
 * 删除文件名的路径
 *
 * 有的浏览器会存在 C:\desktop\aaa.jpg 所以需要格式化成 aaa.jpg
 * /tmp/aaa.jpg  格式化成 aaa.jpg
 *
 * @param name          文件名
 * @param onlyPrefixName         是否只显示前缀名
 * @param onlySuffixName         是否只显示后缀名(onlyPrefixName 为true时该属性无效)
 * @return {string}
 */
export function formatFileNameDeletePath(name,{onlyPrefixName=false,onlySuffixName=false}={}){
    let tmp=name;
    // console.log("tmp1",tmp)
    let i= Math.max(tmp.lastIndexOf("\\"),tmp.lastIndexOf("/"))
    if(i>-1){
        tmp=tmp.substring(i+1);
        return tmp;
    }
    // console.log("tmp2",tmp)
    if(onlyPrefixName||onlySuffixName){
        let spotInd=tmp.lastIndexOf("\.")
        if(spotInd>-1){
            let prefixName=tmp.substring(0,spotInd);
            let suffixName=tmp.substring(spotInd+1);
            if(onlyPrefixName){
                tmp = prefixName
            }else{
                tmp = suffixName
            }
        }
    }
    return tmp;
}


//上传文件时支持的图片格式
export function acceptImage(){
    return `image/gif,image/jpeg,image/png,image/bmp`
}

//数组是否为空
export function arrayIsEmpty(list){
    if (isNullOrUndefined(list)) {
        return true
    }
    return list.length==0

}


/**
 *判断对象是否相等,回转为json后判断
 * @param a
 * @param b
 * @return {boolean}
 */
export function equalsObjectJson(a,b){
    if(isNullOrUndefined(a)&&isNullOrUndefined(b)){
        return true
    }
    if(isNullOrUndefined(a)){
        return false
    }
    if(isNullOrUndefined(b)){
        return false
    }
    return JSON.stringify(a, null)==JSON.stringify(b, null)
}

/**
 * 下载文件
 * @param url
 */
export function handleDownloadFileByUrl(url){
    // window.location.href = file.url
    // let href = url+"?preview=false"
    let href = url
    // window.open(href, '_blank', 'toolbar=yes, width=900, height=700')
    window.open(href, '_blank')

    // window.location.href = href
}

/**
 * 新窗口打开链接
 * @param url
 */
export function handleOpenNewBrowserTab(url){
    let href = url
    window.open(href, '_blank')
}

export function consoleLog(){
    console.log(...arguments)

}

/**
 * 字符串不为空
 * @param val
 * @return {boolean}
 */
export function strIsEmpty(val){
    return isNullOrUndefined(val)||val===''
}

export function strIfEmpty(obj, defaultValue=""){
    if(isNullOrUndefined(obj)){
        return defaultValue
    }
    return obj===''?defaultValue:obj
}

//字符串长度
export function strLength(str){
    if(strIsEmpty(str)){
        return 0
    }
    let tmp=str+''
    return tmp.length
}

//去首尾空
export function strTrim(str){
    if(strIsEmpty(str)){
        return ''
    }
    let tmp=str+''
    // // 去除 空格
    // tmp=tmp.replace(/\ +/g, "");
    // // 去除 换行符
    // tmp=tmp.replace(/[\r\n]/g, "");
    // 去除 前后空格
    tmp=tmp.trim();
    return tmp
}

export function convertDictDataCssClassToJavaEnum(cssClass){
    for (let a of dictDataCssClass) {
        if (isNullOrUndefined(a.childList)) {
            continue
        }
        for(let b of a.childList){
            if (b.dictValue == cssClass) {
                return isNullOrUndefined(b.javaEnum)?'':b.javaEnum
            }
        }
    }
    return 'DictDataCssClass.DEFAULT'
}

export const dictDataCssClass= [
    {
        dictValue: `dictTextColor`,
        dictLabel:"字体颜色",
        childList: [
            {
                javaEnum: 'DictDataCssClass.dictTextColorRed',
                dictValue: `dict-text-color-red`,
                dictLabel:"红色",
            },
            {
                javaEnum: 'DictDataCssClass.dictTextColorGreen',
                dictValue: `dict-text-color-green`,
                dictLabel:"绿色"
            },
        ],

    },
    {
        dictValue: `el-tag颜色`,
        dictLabel:"el-tag--",
        childList: [
            {
                javaEnum: 'DictDataCssClass.dictTextTagPrimary',
                dictValue: `dict-text-tag-primary`,
                dictLabel:"primary(蓝色)"
            },
            {
                javaEnum: 'DictDataCssClass.dictTextTagSuccess',
                dictValue: `dict-text-tag-success`,
                dictLabel:"success(绿色)"
            },
            {
                javaEnum: 'DictDataCssClass.dictTextTagDanger',
                dictValue: `dict-text-tag-danger`,
                dictLabel:"danger(红色)"
            },
            {
                javaEnum: 'DictDataCssClass.dictTextTagWarning',
                dictValue: `dict-text-tag-warning`,
                dictLabel:"warning(黄色)"
            },
            {
                javaEnum: 'DictDataCssClass.dictTextTagInfo',
                dictValue: `dict-text-tag-info`,
                dictLabel:"info(灰色)"
            },
        ],
    }
];

export const defaultSksParamColumnData={
    //自定义插槽
    slot: undefined,
    prop: undefined,
    label: undefined,
    labelWidth: undefined,
    clearable: true,
    visible: true,
    itemStyle: undefined,


    //页面类型
    //none: 自定义
    // <el-option label="文本框" value="input" />
    // <el-option label="文本框-整数" value="inputInteger" />
    // <el-option label="文本框-浮点型" value="inputFloat" />

    // <el-option label="文本域" value="textarea" />
    // <el-option label="下拉框" value="select" />
    // <el-option label="单选框" value="radio" />
    // <el-option label="复选框" value="checkbox" />
    // <el-option label="日期控件" value="datetime" />
    // <el-option label="上传控件" value="uploadImage" />
    // <el-option label="富文本控件" value="editor" />
    //sksFilterParamDateRange 日期范围选择
    //sksFilterParamSearchValueList 通用文本搜索
    htmlType: 'input',

    //精度, htmlType=数字形式时有效
    precision: undefined,
    //最小值, htmlType=数字形式时有效
    min: undefined,
    //最大值, htmlType=数字形式时有效
    max: undefined,
}




export const sksParamsPropConfigAvailableValueTypeOptions= {
    string:{
        dictValue: 'String',
        dictLabel: '字符串'
    },
    number:{
        dictValue: 'Number',
        dictLabel: '数字'
    },
    boolean:{
        dictValue: 'Boolean',
        dictLabel: '布尔'
    },
}



export function getSelectTitleByColumnConfig(columnConf) {
    let data = columnConfigToSelectTitle(columnConf);
    // console.log('getSelectTitleByColumnConfig',data)
    return data
}

function columnConfigToSelectTitle(columnConf={}){
    const data={}
    for (let key of Object.keys(columnConf)) {
        let value=columnConf[key]
        if(isNullOrUndefined(value.label)){
            data[key]=columnConfigToSelectTitle(value)
        }else{
            if(value.label.constructor === String){
                data[key]=value.label
            }else{
                data[key]=columnConfigToSelectTitle(value)
            }
        }
    }
    return data
}

export function getIndexByUUIDTable(list,row){
    if (isNullOrUndefined(list)||isNullOrUndefined(row.vueVirtualUUID)) {
        return -1;
    }
    let index=-1;
    for (let item of list) {
        index++
        if (item.vueVirtualUUID === row.vueVirtualUUID) {
            return index;
        }
    }
    return -1;
}

export function resetSksTableBefore(sksTable, clearList=false){
    if(clearList){
        sksTable.list=[]
    }
    sksTable.currentRow=undefined
    sksTable.loading=true
}

/**
 * 删除list中的 vueVirtualUUID 的行
 * 用于新增之后主键无值,row的key不能用list中的索引为,避免多个table时报错
 * 每个row数据时默认设置 vueVirtualUUID 的值为 生成的UUID
 * @param list
 * @param row
 */
export function deleteFromVueVirtualUUID(list,vueVirtualUUID) {
    // 1.根据ID来找到要删除的这一项的索引
    // 2. 找到索引后，调用数组的splice方法
    // 方法一
    list.some((item,i)=>{
        // console.log('deleteFromVueVirtualUUID',item.vueVirtualUUID==vueVirtualUUID)
        if(item.vueVirtualUUID==vueVirtualUUID){
            list.splice(i,1);
            // 在数组的some方法中，如果return true，就会立即终止这个数组的后续循环,所以相比较foreach，如果想要终止循环，那么建议使用some
            return true;
        }
    })
}

/**
 * 获取变更的行集合,原list不受影响,会生成新的集合
 * @param listIn
 * @returns  Array
 */
export function getNewChangeRowList(listIn){
    if(listIn==undefined||listIn.constructor != Array||listIn.length==0){
        if(listIn.constructor != Array){
            console.error("listIn=",listIn)
            throw new Error("listIn不是Array类型")
        }
        return [];
    }

    let list=listIn.filter ( item =>{
        //   &1:  新增 toBeAdd()    判断 true:需新增
        //   &2:  修改 toBeModify() 判断 true:需更新
        //   &4:  修改 toBeDelete() 判断 true:需删除
        if (isNullOrUndefined(item.virtualChangeBitFlag)|| item.virtualChangeBitFlag == 0) {
            return false;
        }
        return true;
    })
    return list;
}

export function setSksTableDataByPage(sksTable, page){
    let list = page.list;
    initListVueVirtualUUID(list)
    sksTable.list= list
    sksTable.total=page.total
    sksTable.loading=false
}

export function formatDateToDateTimeYmd00000(val){
    let tmp=val
    if(isNullOrUndefined(tmp)){
        return undefined
    }
    if (tmp.length == 10) {
        tmp=tmp+" 00:00:00"
    }
    return tmp
}

/**
 * list重新排序,根据 mainTable.sortPropName 使用 Asc
 * @param sksTable
 * @param sortPropName          排序的字段
 */
export function resortTableSortPropNameAsc({sksTable,sortPropName="sort"}={}){
    if (strIsEmpty(sortPropName)) {
        return
    }

    sksTable.list.sort((a,b)=>{
        if (a.virtualChangeBitFlag == CHANGE_BIT_FLAG.delete) {
            return
        }
        return a[sortPropName]-b[sortPropName]
    })
}

/**
 * list排序字段值重置,根据 mainTable.sortPropName
 * @param sksTable
 * @param sortPropName          排序的字段
 */
export function resetTableSortPropNameValue({sksTable,sortPropName="sort",cacheTable=true}={}){
    let sort=1;
    for (let row of sksTable.list) {
        row[sortPropName]=sort*10
        sort++
    }
}

//是否存在有效文件
export function hasValidDocument(virtualDocumentList) {
    if (isNullOrUndefined(virtualDocumentList)) {
        return false
    }
    return virtualDocumentList.some(obj=>{
        return obj.virtualChangeBitFlag!=CHANGE_BIT_FLAG.delete
    })
}

//是否存在有效行
export function hasValidTableRow(list){
    if (isNullOrUndefined(list)) {
        return false
    }
    return list.some(obj=>{
        return obj.virtualChangeBitFlag!=CHANGE_BIT_FLAG.delete
    })
}

//true: 数组是否为空或者无元素
export function listIsEmpty(list){
    if (isNullOrUndefined(list)) {
        return true;
    }
    return list.length==0;
}


/**
 * 查找最适合查询的属性名
 * equals 优先
 * @param queryParamsColumnList
 *
 let propName = findQueryPropByQueryParamsColumnList({
                    queryParamsColumnList: this.mainTable.queryParamsColumnList,
                    propName: 'proName',
                })
 */
export function findQueryPropByQueryParamsColumnList({queryParamsColumnList,propName}={}){
    if (isNullOrUndefined(queryParamsColumnList)) {
        return undefined
    }
    let tmp=undefined;
    let tmpEquals=undefined
    for (let row of queryParamsColumnList) {
        if (row.propName.startWith(propName)) {
            if (row.propName == propName + 'Equals') {
                tmpEquals=undefined
            }
        }
    }
    if(tmpEquals){
        return tmpEquals
    }
    return tmp
}

/**
 * 格式化 下拉选择 时的label
 * @param item
 * @param optionKey
 * @param valType
 * @param separator
 * @param relationshipNameList          行数据的属性名字符串集合,支持子级,用 . 分割
 * @return {string}
 *
 :format-option-label="(item)=>baseFormatOptionLabel({ item: item, optionKey: `proProcedureTaskId`, relationshipNameList: [`workshopName`,`procedureConfName`] })"
 */
export function baseFormatOptionLabel({item,optionKey,valType=`number`,separator=`-`,relationshipNameList=[]}){
    if(isNullOrUndefined(item)){
        return `下拉选择行数据为空`
    }
    if(!isNullOrUndefined(optionKey)){
        if(valType==`number`){
            if(numberIsZeroOrNull(item[optionKey])){
                return `(请选择或搜索)`
            }
        }else{
            if(strIsEmpty(item[optionKey])){
                return `(请选择或搜索)`
            }
        }
    }
    let valueList=[]
    for (let relationshipName of relationshipNameList) {
        let value = safeGetNullEmpty(item,relationshipName)
        valueList.push(value)
    }
    return formatSelectLabel({
        separator: separator,
        valueList: valueList
    })
}

//格式化 下拉选择 时的label
export function formatSelectLabel({separator=`-`,valueList=[]}={}){
    // console.log("formatSelectLabel.separator,valueList",separator,valueList)
    let tmp=[]
    for (let val of valueList) {
        if (!strIsEmpty(val)) {
            tmp.push(val)
        }
    }
    let s = tmp.join(separator)
    // console.log("formatSelectLabel.s",s)
    return s
}

/**
 * 如果不为空则拼接,否则返回空字符
 */
export function notEmptyAppend(val,prefix,suffix){
    if (strIsEmpty(val)) {
        return ""
    }
    let tmp=val
    if (strIsEmpty(prefix)) {
        tmp=`${prefix}${tmp}`;
    }
    if (strIsEmpty(suffix)) {
        tmp=`${tmp}${suffix}`;
    }
    return tmp;
}

export function initTreeVueVirtualUUID({list,hasVirtualChangeBitFlag=true,hasIsSet=true,childrenProp='children'}){
    if(list == undefined){
        return [];
    }
    list.forEach((item,i)=>{
        initRowVueVirtualUUID(item,hasVirtualChangeBitFlag,hasIsSet)
        if(!arrayIsEmpty(item[childrenProp])){
            initTreeVueVirtualUUID({
                list: item[childrenProp],
                hasVirtualChangeBitFlag: hasVirtualChangeBitFlag,
                hasIsSet: hasIsSet,
                childrenProp: childrenProp,
            })
        }
    })
    return list;
}

export function initListVueVirtualUUID(list,hasVirtualChangeBitFlag=true,hasIsSet=true){
    if(list == undefined){
        return [];
    }
    list.forEach((item,i)=>{
        initRowVueVirtualUUID(item,hasVirtualChangeBitFlag,hasIsSet)
    })
    return list;
}

/**
 * 初始化列表行的uuid
 * @param item
 * @return {*}
 */
export function initRowVueVirtualUUID(item,hasVirtualChangeBitFlag=true,hasIsSet=true){
    if(hasVirtualChangeBitFlag){
        if(isNullOrUndefined(item.virtualChangeBitFlag)){
            item.virtualChangeBitFlag=0
        }
    }
    if(isNullOrUndefined(item.vueVirtualUUID)){
        item.vueVirtualUUID=generateUUID();
        if(hasIsSet){
            item.isSet=false;
        }
    }
    return item;
}


/**
 * 如果 vueVirtualUUID 不存在则生成
 * 主要用于组件中 for循环需要一个key
 * @param item
 * @return {string}  vueVirtualUUID 的值
 */
export function genRowVueVirtualUUID(item){
    let vueVirtualUUID=item.vueVirtualUUID
    if(isNullOrUndefined(vueVirtualUUID)){
        vueVirtualUUID=generateUUID();
        item.vueVirtualUUID=vueVirtualUUID
    }
    return vueVirtualUUID;
}

/**
 * 清除属性校验错误信息
 * @param propName
 */
export function clearFormValidate(propName){
    this.$refs?.form?.clearValidate(propName)
}



/**
 * 格式化ossUrl
 * @param url
 * @param spm
 * @param suffix
 * @return {string|*}
 */
export function formatOssUrl({url,spm=true,suffix=''}){
    if(spm===false||suffix===undefined||url===undefined||url==''){
        return url;
    }
    //url中存在?,直接返回
    if (url.indexOf('?') > -1) {
        return url;
    }

    //后缀中存在 ?, 直接拼接后返回
    if (suffix.indexOf('?') > -1) {
        return url+suffix;
    }
    return url+'?'+suffix

}

/**
 * arr 中是否存在 value
 * @param arr
 * @param value
 * @param typeEqual
 * @return {boolean}
 */
export function isInArray(arr,value,typeEqual=false){
    if(arr===undefined||value===undefined){
        return false;
    }
    // console.log("typeEqual=",typeEqual)
    if(typeEqual){
        for(let i = 0; i < arr.length; i++){
            if(value === arr[i]){
                return true;
            }
        }
    }else{
        for(let i = 0; i < arr.length; i++){
            // console.log("arr[i]",arr[i])
            // console.log("value",value)
            if(value == arr[i]){
                return true;
            }
        }
    }
    return false;
}
/**
 * 查找list中对应字段相同的row
 * @param list
 * @param attrName      list中row的字段名
 * @param value         要查找的value值
 * @param typeEqual     类型是否一致,false:== , true:===
 * @returns {undefined|*}
 */
export function findRowIndexInListFromAttrName(list,attrName,value,typeEqual=false){
    if (value == null) {
        return -1;
    }
    if (isNullOrUndefined(list)||isNullOrUndefined(attrName)) {
        return -1;
    }
    let index=-1
    for (let i = 0; i < list.length; i++) {
        index++
        if(typeEqual){
            if (list[i][attrName] === value) {
                return index;
            }
        }else{
            if (list[i][attrName] == value) {
                return index;
            }
        }
    }
    return -1;
}

/**
 * true: 值无效, 无效值如下
 *          null
 *          undefined
 *          空字符
 *          数字为0
 */
export function isInvalid(val){
    if(numberIsZeroOrNull(val)){
        return true;
    }
    if (strIsEmpty(val)) {
        return true;
    }
    return false;
}
// 日期格式化
export function parseTime(time, pattern) {
    if (arguments.length === 0 || !time) {
        return null
    }
    const format = pattern || '{y}-{m}-{d} {h}:{i}:{s}'
    let date
    if (typeof time === 'object') {
        date = time
    } else {
        if ((typeof time === 'string') && (/^[0-9]+$/.test(time))) {
            time = parseInt(time)
        } else if (typeof time === 'string') {
            time = time.replace(new RegExp(/-/gm), '/');
        }
        if ((typeof time === 'number') && (time.toString().length === 10)) {
            time = time * 1000
        }
        date = new Date(time)
    }
    const formatObj = {
        y: date.getFullYear(),
        m: date.getMonth() + 1,
        d: date.getDate(),
        h: date.getHours(),
        i: date.getMinutes(),
        s: date.getSeconds(),
        a: date.getDay()
    }
    const time_str = format.replace(/{(y|m|d|h|i|s|a)+}/g, (result, key) => {
        let value = formatObj[key]
        // Note: getDay() returns 0 on Sunday
        if (key === 'a') { return ['日', '一', '二', '三', '四', '五', '六'][value] }
        if (result.length > 0 && value < 10) {
            value = '0' + value
        }
        return value || 0
    })
    return time_str
}
/**
 * 多个空格替换为1个空格
 * @returns {*}
 */
export function resetBlank(str){
    if(!str)return str;
    const regEx = /\s+/g;
    return str.replace(regEx, ' ');
}

export function bitFlagToArray(bigFlag){
    // console.log("bitFlagToArray.in=",bigFlag)
    let tmp=1;
    const arr=[];
    while (bigFlag>=tmp){

        if(tmp&bigFlag){
            arr.push(tmp);
        }
        //左移一位
        tmp=tmp<<1
    }
    // console.log("bitFlagToArray.out=",arr)
    return arr;
}

export function bitFlagToStringArray(bigFlag){
    // console.log("bitFlagToStringArray.in=",bigFlag)
    let tmp=1;
    const arr=[];
    while (bigFlag>=tmp){

        if(tmp&bigFlag){
            arr.push(tmp+'');
        }
        //左移一位
        tmp=tmp<<1
    }
    // console.log("bitFlagToStringArray.out=",arr)
    return arr;
}

export function arrayToBitFlag(arr){
    // console.log("arrayToBitFlag.in=",arr)
    let tmp=0;
    arr.forEach((obj)=>{
        tmp=tmp|parseInt(obj);
    })
    // console.log("arrayToBitFlag.out=",tmp)
    return tmp;
}

/**
 * bitFlagAndNumber(8,1) return false;
 * 与运算
 * @param bitFlag
 * @returns {boolean}
 */
export function bitFlagAndNumber(bitFlag,num){
    if(bitFlag&&num){
        return true;
    }
    return false;
}
